
--[[
	消息处理

--]]
local cjson = require("cjson")
local table_insert = table.insert
local math_random = math.random
local math_floor = math.floor

---------------------------------------------------------
-- class
---------------------------------------------------------
local M = class("Robot")

function M:ctor(info)
    self.game_node = nil
    self.table_name = "texas_bot_info"
    self.robot_info = info
    self.uid = info.mid
    self.mid = info.mid
    self.type = info.type --机器人类型
    self.tid = nil
    self.seatid = nil

    self.user_data = {
        fd = nil,
        uid = self.mid,
        nickname = ""..self.mid,
        gold = 0,
        agent = g.service_id,
        remote = g.getNodeFullName(),
        robot = true,
    }
    self.cards = {}
    self.play_start_time = 0
    self.play_time = g.time() --进入游戏的时间
    self.status = {
        init = 0,
        enter = 1,
        stand = 2,
        play = 3,
    }
    self.cur_status = self.status.init
    self.show_cards = false --亮牌
    
    --g.loop(1000, function()
    --    self:update()
    --end)
    if info.tid and #info.tid > 0 and info.running > 0 then
        --self.cur_status = self.status.play
        g.timeout(2, function()
            self:checkReload(info.tid)
        end)
    end

    self:register()
end

function M:register()
    self.tb_callback = {
        C2_TS_sit= handler(self, self.resDeskSitdown),
        TS_2C_sitBc= handler(self, self.resDeskSitdownBc),
        C2_TS_standup= handler(self, self.resDeskSitup),
        TS_2C_standupBc= handler(self, self.resDeskSitupBc),
        C2_TS_leave= handler(self, self.resDeskLeave),
        TS_2C_leaveBc= handler(self, self.ntDeskLeaveBc),
        TS_2C_nextbetBc= handler(self, self.ntNextBet),
        TS_2C_gamebeginBc= handler(self, self.ntGameBegin),
        C2_TS_bet= handler(self, self.resBet),
        TS_2C_buttonBc= handler(self, self.ntButton),
        TS_2C_betBc= handler(self, self.ntBet),
        TS_2C_preflop= handler(self, self.ntPreflop),
        TS_2C_flopBc= handler(self, self.ntFlop),
        TS_2C_turnBc= handler(self, self.ntTurn),
        TS_2C_riverBc= handler(self, self.ntRiver),
        TS_2C_gameoverBc= handler(self, self.ntGameover),
        TS_2C_potBc= handler(self, self.ntPot),
        TS_2C_enterBc= handler(self, self.ntEnter),
        TS_2C_upblindBc= handler(self, self.ntUpblindBc),
        TS_2C_eventBc= handler(self, self.ntEventBc),
        GS_2C_updateuser= handler(self, self.ntUpdateUser),
        TS_2C_showcardsBc= handler(self, self.ntShowCard),
        TS_2C_AutoOperBc = handler(self, self.ntAutoOper),
    }

end

function M:send(cmd, data)
    if not self.game_node then
        self.game_node = g.call(".cluster.service", "node_get_one", "ndgame.*")
    end
    if self.game_node then
        return g.message:sendNode(self.game_node, ".games.service", cmd, data)
    end
end

function M:call(cmd, data)
    if not self.game_node then
        self.game_node = g.call(".cluster.service", "node_get_one", "ndgame.*")
    end
    if self.game_node then
        return g.message:callNode(self.game_node, ".games.service", cmd, data)
    end
end

--玩家基本信息
function M:getInfo()
    if self.info then
        return self.info
    end
    self.info = g.dp:getUserInfo(self.uid)
end

function M:setStatus(status)
    self.cur_status = status
    if status == self.status.init then
        self.seatid = nil
        --self.tid = nil
    end
end

function M:getCurStatus()
    return self.cur_status
end

function M:isIdle()
    return self.cur_status == self.status.init
end

function M:setGameNode(node)
    self.game_node = node
end

function M:logInfo(...)
    --g.log:info(...)
    --g.log:warn(...)
end

function M:update()
    if g.time() - self.play_time > 300 then
        self.play_time = g.time()
        if self:isIdle() then return end
        if not self.seatid and self:getCurStatus() ~= self.status.play then
            g.timeout(2, function()
                g.log:warn("robot leave:", self.mid, self.tid, self:getCurStatus())
                self:reqDeskLeave()
            end)
        end
    end
end

--检查机器人身上的金币
function M:checkChips(rid, tid)
    local mid = self.mid
    local chips = self.chips or 30000
    local cur_chip = g.dp:getUserChip(mid)
    if not cur_chip then
        --取不到金币
        g.log:err("get chip faild mid:", mid)
        return false
    end
    --金币比较多还回去一些
    local max_chip = cur_chip - chips
    if max_chip > 500000 then
        max_chip = 500000
        local ok = g.dp:updateBotChipsPool(max_chip)
        if not ok then
            g.log:err("updateBotChipsPool add ", max_chip)
            return false
        end
        local ok = g.dp:setUserChip(mid, -max_chip)
        if ok then
            local user_chips = -max_chip + cur_chip
            local flag = g.const.chip.s_f_descr --增加或减少的标记
            --写流水
            local data = {
                mid = mid,
                chips = max_chip, --变化值
                mode = g.const.chip.s_m_bot_rechange,
                remark = rid,
                desc = "robot back pool",
                tid = tid,
                bonus = 0,
                winning = 0,
                flag = flag,
                chips_result = user_chips, --最终结果
                bonus_result = 0,
                winning_result = 0,
                game_type = 1, --系统派发
                ltype = 1,
                ltime = g.getMsec(),
            }
            g.sendLogs( "logs_chips", data)
            return true
        else
            local ok = g.dp:updateBotChipsPool(-max_chip)
            if not ok then
                --返还金币到池子失败
                g.log:err("updateBotChipsPool back chips faild! chip:", max_chip)
            end
            g.log:err("setUserChip chips faild! mid:", mid, -max_chip)
            return false
        end
    end

    --从池子里扣除金币放到机器人身上
    local pool = g.dp:getBotChipsPool()
    if not pool then
        g.log:err("getBotChipsPool get chip faild mid:", mid)
        return false
    end
    if cur_chip and cur_chip < chips then
        --从池子里扣除
        local need_chip = chips - cur_chip
        if pool.chips < need_chip then
            g.log:warn("pool.chips too less", pool.chips , need_chip)
            return false
        end
        local ok = g.dp:updateBotChipsPool(-need_chip)
        if not ok then
            g.log:err("updateBotChipsPool sub ", max_chip)
            return false
        end
        local ok = g.dp:setUserChip(mid, need_chip)
        if ok then
            local user_chips = need_chip + cur_chip
            local flag = g.const.chip.s_f_add --增加或减少的标记
            if need_chip < 0 then
                flag = g.const.chip.s_f_descr
            end
            --写流水
            local data = {
                mid = mid,
                alter_value = need_chip, --变化值
                mode = g.const.chip.s_m_bot_rechange,
                remark = rid,
                desc = "robot buy in",
                tid = tid,
                flag = flag,
                current_value = user_chips, --最终结果
                game_type = 1, --系统派发
                ltype = 1,
                ltime = g.getMsec(),
            }
            g.sendLogs( "logs_chips", data)
            return true
        else
            local ok = g.dp:updateBotChipsPool(need_chip)
            if not ok then
                --返还金币到池子失败
                g.log:err("setUserChip faild! chip:", need_chip)
            end
            g.log:err("setUserChip chips faild! mid:", mid, need_chip)
            return false
        end
    end
    return true
end

-----------------------------------------------------------

-----------------------------------------------------------
--请求进入桌子
function M:reqEnterDesk(rid, rtype, tid)
    if g.closed then return end
    self:setStatus(self.status.enter)
    if rid then
        local room_cfg = g.callConfig("get", "room_cfg", rid)
        if room_cfg then
            if math_random(1, 2) == 1 then
                self.chips = math_floor(room_cfg.max_buy / 2)
            else
                self.chips = math_floor(room_cfg.max_buy)
            end
        end
    end

    local mid = self.mid
    local chips = self.chips or 30000
    local info = ""
    self:getInfo()
    if self.info then
        info = cjson.encode({
            big_pic = self.info.big_pic,
            name = self.info.name,
        })
    end
    if rtype == g.const.room_type.normal and rid then
       if not self:checkChips(rid, tid) then
            self:setStatus(self.status.init)
            g.log:info("checkChips faild:", rid, tid)
            return
       end
    elseif tid then
        --重进桌子
        g.log:info("tid:", self.mid, tid)
    else
        g.log:err("no rid mid:", self.mid)
        self:setStatus(self.status.init)
        return
    end

    local msg = {
        mid = mid,
        rid = rid,
        chips = chips,
        rtype = rtype,
        tid = tid,
        info = info,--{\"big_pic\":\"https://7flowerhk.oss-cn-hongkong.aliyuncs.com/gamepic/2.jpg\",\"name\":\"mTerrell\",\"pf\":\"pf_0\",\"vip_point\":0,\"league\":1}
    }
    msg.user_data = self.user_data
    --请求进入桌子
    local res = self:call("C2_TS_enter", msg)
    --g.log:debug("111enter res:", res)
    if res and res.code == g.error_code.ok then
        self:resDeskEnter(res)
    else
        --入桌失败离开
        self:logInfo("enter err res:", self.mid, res)
        self:resDeskLeave()
    end
end

--是否已经在桌子里玩
function M:checkReload(tid)
    --local data = g.dp:getUserPos(self.mid)
    --print("1checkReload:", tid, self.mid, tostring(data))
    --if not data or not data.address then return end
    --print("checkReload:", tid, self.mid, tostring(data))
    --self.game_node = data.nodefullname
    self:reqEnterDesk(_, _, tid)
    --g.sleep(100)
end

--比赛场入桌
function M:resDeskEnter(msg)
    self:logInfo("resDeskEnter data:", msg)
    if msg.code ~= 0 then
        return
    end
    self.rid = msg.roominfo.rid
    self.tid = msg.roominfo.tid
    self.rtype = msg.rtype
    self:setStatus(self.status.stand)
    self.play_time = g.time()
    --设置机器人状态
    g.dp:updateBotStatus(self.table_name, self.rid, self.mid, self.tid)
    --g.dp:setUserPos(self.mid, self.tid)
    if msg.rtype and msg.rtype == 0 and msg.seatid == 0 then
        g.timeout(1, function ()
            --if self.status:toSitDoing() == false then return end
            self:reqDeskSitdown()
        end)
    else
        --g.log:warn("resDeskEnter:", msg)
        self:setStatus(self.status.play)
    end
end

function M:reqDeskLeave()
    --if self.status:toLeaveDoing() == false then
    --    return
    --end
    if not self.tid then return end
    if g.closed then return end
    local data = {
        mid = self.mid,
        tid = self.tid,
    }
    local res = self:call("C2_TS_leave", data)
    if res then
        self:resDeskLeave(res)
    else
        g.log:warn("reqDeskLeave res is nil", res)
    end

end

function M:resDeskLeave(msg)
    self:logInfo("resDeskLeave data:", msg)
    self.tid = nil
    if self:getCurStatus() == self.status.init then
        return
    end
    self:setStatus(self.status.init)
    g.dp:updateBotStatus(self.table_name, 0, self.mid)
    g.dp:removeUserPos(self.mid)
end

function M:ntDeskLeaveBc(msg)
    --self:logInfo("ntDeskLeaveBc data:", msg)
    if msg.mid ~= self.mid then
        return
    end
    if not self.tid then return end
    self.tid = nil
    self:setStatus(self.status.init)
    g.dp:updateBotStatus(self.table_name, 0, self.mid)
    g.dp:removeUserPos(self.mid)
    --g.log:warn("ntDeskLeaveBc:", msg.mid, self.mid, msg.mid == self.mid)
end

function M:reqDeskSitdown()
    if not self.tid then return end
    local data = {
        mid = self.uid,
        tid = self.tid,
        seatid = 0,
        chips = self.chips,
    }
    local res = self:call("C2_TS_sit", data)
    if res then
        self:resDeskSitdown(res)
    end
end

function M:resDeskSitdown(msg)
    --g.log:warn("resDeskSitdown data:", msg)
    if msg.code ~= g.error_code.ok then
        g.timeout(1, function()
            self:reqDeskLeave()
            self:setStatus(self.status.init)
        end)
        return
    end
    self.play_start_time = g.time()
    self.seatid = msg.seatid
    self:setStatus(self.status.play)
end

function M:resDeskSitdownBc(msg)
    self:logInfo("resDeskSitdownBc data:", msg)
end

function M:reqDeskSitup()
    local data = {
        mid = self.uid,
        tid = self.tid,
    }
    local res = self:call("C2_TS_standup", data)
    self:resDeskSitup(res)

end

function M:resDeskSitup(msg)
    self:logInfo("resDeskSitup data:", msg)
    self.seatid = nil
    g.timeout(1, function()
        self:reqDeskLeave()
    end)
end

function M:resDeskSitupBc(msg)
    self:logInfo("resDeskSitupBc data:", msg)
    if self.mid ~= msg.mid then return end
    g.timeout(1, function()
        self:reqDeskLeave()
    end)
end

function M:ntNextBet(msg)
    self:logInfo("ntNextBet data:", msg)
    if not self.tid then
        self:reqDeskLeave()
        return
    end
    if self.uid ~= msg.mid then
        return
    end
    local bet = msg.follow_bet
    if math_random(1, 3) == 1 then
        bet = 0
    end
    if bet > msg.max_bet then
        bet = msg.max_bet --allin
    end
    --print("##############bet  ################= handler(self, self.uid, bet)
    --local sleep = math_random(300,600)
    --g.sleep(sleep)
    --self:reqBet(self.mid, bet)

end

function M:ntGameBegin(msg)
    self:logInfo("ntGameBegin data:", msg)
    self.cards = {}
    self.show_cards = false
end

function M:reqBet(uid, chips)
    uid = uid or self.uid
    chips = chips or 0
    local tid = self.tid
    if not tid then
        g.log:err("reqBet no tid ", tid, uid, chips)
        return
    end
    local data = {
        mid = uid,
        tid = tid,
        chips = chips,
    }
    self:send("C2_TS_bet", data)
end

function M:resBet(msg)
    self:logInfo("resBet data:", msg)
end

function M:ntButton(msg)
    self:logInfo("ntButton data:", msg)
end

function M:ntBet(msg)
    self:logInfo("ntBet data:", msg)
    if msg.mid == self.mid and msg.action and msg.action == -1 then
        if math_random(1, 8) == 1 then
            self:reqShowCard()
        end
    end
end

function M:ntPreflop(msg)
    self:logInfo("ntPreflop data:", msg)
    self.cards = msg.card

end

function M:ntFlop(msg)
    self:logInfo("ntFlop data:", msg)

end

function M:reqShowCard()
    if not self.tid then return end
    if self.show_cards then return end
    self.show_cards = true
    if not self.cards or not next(self.cards) then return end
    local data = {
        mid = self.mid,
        tid = self.tid,
        cards = self.cards,
    }
    self:send("C2_TS_showcard", data)
end

function M:ntTurn(msg)
    self:logInfo("ntTurn data:", msg)
end

function M:ntRiver(msg)
    self:logInfo("ntRiver data:", msg)
end

function M:ntGameover(msg)
    self:logInfo("ntGameover data:", msg)
    if self.rtype ~= 0 then return end

    --local users = msg.users
    --local my_user = nil
    --local loser = nil
    --for _, user in pairs(users) do
    --    if user.mid == self.mid and user.win > 0 then
    --        if math_random(1, 4) == 1 then
    --            self:reqShowCard()
    --        end
    --        my_user = user
    --    end
    --    if user.win < 0 then
    --        loser = user
    --    end
    --end
    --self.cards = {}
    ----if not my_user then
    ----输了离开
    --if g.time() - self.play_start_time > 200 then
    --    --self.play_start_time = g.time()
    --    if 1 == math_random(1, 3) then
    --        --g.log:warn("game over robot leave req", self.uid, self.tid)
    --        g.timeout(math_random(2, 5), function()
    --            self:reqDeskLeave()
    --            return
    --        end)
    --        return
    --    end
    --end
    ----end
    --
    --if my_user and loser then
    --    local num = math_random(1, 15)
    --    if num == 1 then
    --        g.timeout(math_random(2, 4), function()
    --            self:reqMessage()
    --        end)
    --    elseif num == 2 then
    --        g.timeout(math_random(2, 4), function()
    --            self:reqMagicMsg(loser.mid)
    --        end)
    --    elseif num == 3 then
    --        g.timeout(math_random(2, 4), function()
    --            self:reqTextMsg()
    --        end)
    --    end
    --end



end

function M:ntPot(msg)
    self:logInfo("ntPot data:", msg)
end

function M:ntEnter(msg)
    self:logInfo("ntEnter data:", msg)
end

function M:ntUpblindBc(msg)
    self:logInfo("ntUpblindBc data:", msg)
end

function M:ntEventBc(msg)
    local data = {}
    --print("msg:", msg.msg)
    if msg.msg then
        data = cjson.decode(msg.msg)
    end
    self:logInfo("ntEventBc data:", data)
end

function M:ntUpdateUser(msg)
    self:logInfo("ntUpdateUser data:", msg)
end

function M:ntShowCard(msg)
    self:logInfo("ntShowCard data:", msg)
    if msg and msg.cards then
        for _, card in pairs(msg.cards) do
            if card.seatid and card.seatid == self.seatid then
                --已经被亮牌
                self.show_cards = true
            end
        end
    end
end

function M:ntAutoOper(msg)
    self:logInfo("ntAutoOper data:", msg)
end

function M:reqMessage()
    if not self.tid then return end
    --表情， 4，13， 23
    local tb = {
        4, 6, 13, 16, 23,
    }
    local msg = {
        type = "chat",
        emoji = tb[math_random(1,#tb)],
    }
    local data = {
        mid = self.uid,
        tid = self.tid,
        msg = cjson.encode(msg),
    }
    self:send("C2_TS_message", data)
    g.log:debug("reqMessage:", data)
end

function M:reqTextMsg()
    if not self.tid then return end
    local tb = {
        "Thanks!", "Nice Play!", "I'am Lucky!",
    }
    local msg = {
        type = "chat",
        msg = tb[math_random(1,#tb)],
    }
    local data = {
        mid = self.uid,
        tid = self.tid,
        msg = cjson.encode(msg),
    }
    self:send("C2_TS_message", data)
    g.log:debug("reqMessage:", data)
end

--魔法表情
function M:reqMagicMsg(mid)
    if not self.tid then return end
    local tb = {
        "rose", "beer"
    }
    local msg = {
        type = "one_to_one",
        toMid = to_mid,
        key = tb[math_random(1,#tb)],
    }
    local data = {
        mid = self.uid,
        tid = self.tid,
        msg = cjson.encode(msg),
    }
    self:send("C2_TS_message", data)
    g.log:debug("reqMagicMsg:", data)
end

return M
